package cn.secby.common.core.web.mapper;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.jetbrains.annotations.Nullable;
import org.springframework.util.ObjectUtils;
import java.lang.reflect.Field;

public class WrapperParse {

    /****
     * 对QueryWrapper进行封装
     */
    public static QueryWrapper queryGL(Object instance,String minProName,boolean minIsEq,String maxProName,boolean maxIsEq){
        //1、获取Class
        Class<?> clazz = instance.getClass();
        QueryWrapper query = new QueryWrapper();
        query.setEntityClass(clazz);

        //2、构建查询条件
        try {
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                //2.1 暴力破解
                field.setAccessible(true);
                //2.2 获取名字
                String name = field.getName();
                String columnName = name;
                if(name.equals("serialVersionUID")){
                    continue;
                }

                //2.3 获取字段类型
                String clazzName = field.getDeclaringClass().getName();
                //2.4 String则拼接like
                if("java.lang.String".equals(clazzName)){
                    stringMatch(instance, query, field, name, columnName);
                }
                else if("java.util.Date".equals(clazzName) || "java.time.LocalDateTime".equals(clazzName) || "java.time.LocalDate".equals(clazzName) || "java.lang.Double".equals(clazzName) || "java.lang.Integer".equals(clazzName) || "java.lang.Long".equals(clazzName) || "java.lang.Float".equals(clazzName) || "java.lang.Short".equals(clazzName)){
                    if(!ObjectUtils.isEmpty(minProName) && name.equals(minProName)){
                        if(minIsEq){
                            query.ge(columnName, field.get(instance));
                        }else{
                            query.gt(columnName, field.get(instance));
                        }
                    }else if(!ObjectUtils.isEmpty(maxProName) && name.equals(maxProName)){
                        if(maxIsEq){
                            query.le(columnName, field.get(instance));
                        }else{
                            query.lt(columnName, field.get(instance));
                        }
                    }else {
                        reDateMatch(instance, query, field, columnName);
                    }
                }//2.5 如果clazzName不是Date或者LocalDateTime或者LocalDate，则使用query.eq拼接
                else if(!"java.util.Date".equals(clazzName) && !"java.time.LocalDateTime".equals(clazzName) && !"java.time.LocalDate".equals(clazzName)){
                    reDateMatch(instance, query, field, columnName);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return query;
    }

    /****
     * 对QueryWrapper进行封装
     */
    public static QueryWrapper query(Object instance){
        return queryGL(instance,null,false,null,false);
    }

    /****
     * 对QueryWrapper进行封装
     */
    public static QueryWrapper query(Object instance,String minProName){
        return queryGL(instance,minProName,false,null,false);
    }

    /****
     * 对QueryWrapper进行封装
     */
    public static QueryWrapper query(Object instance,String minProName,String maxProName){
        return queryGL(instance,minProName,false,maxProName,false);
    }

    /****
     * 对QueryWrapper进行封装
     */
    public static QueryWrapper queryMinEq(Object instance,String minProName,Boolean isEq){
        return queryGL(instance,minProName,isEq,null,false);
    }

    /****
     * 对QueryWrapper进行封装
     */
    public static QueryWrapper queryMaxEq(Object instance,String maxProName,Boolean isEq){
        return queryGL(instance,null,false,maxProName,isEq);
    }

    /****
     * 对QueryWrapper进行封装
     */
    public static QueryWrapper queryBetween(Object instance,String minProName,Boolean minIsEq,String maxProName,Boolean maxIsEq){
        return queryGL(instance,minProName,minIsEq,maxProName,maxIsEq);
    }

    /***
     * 非日期类型匹配
     * @param instance
     * @param query
     * @param field
     * @param columnName
     */
    public static void reDateMatch(Object instance, QueryWrapper query, Field field, String columnName) {
        try {
            Object value = field.get(instance);
            //2.5 获取@TableField注解中的value值
            columnName = getColumnName(field, columnName);
            if(ObjectUtils.isEmpty(columnName)) {
                return;
            };
            query.eq(!ObjectUtils.isEmpty(value), columnName,value);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /****
     * 字符串匹配，这里包含了like查找
     * @param instance
     * @param query
     * @param field
     * @param name
     * @param columnName
     */
    public static void stringMatch(Object instance, QueryWrapper query, Field field, String name, String columnName) {
        try {
            String value = (String) field.get(instance);
            //2.5 获取@TableField注解中的value值  排除非数据库字段和逻辑删除字段
            columnName = getColumnName(field, columnName);
            if(ObjectUtils.isEmpty(columnName)) {
                return;
            };

            //2.6 如果name中带有name，则用like组装，否则用eq组装
            if(name.toLowerCase().contains("key") || name.toLowerCase().contains("name") || name.toLowerCase().contains("title") || name.toLowerCase().contains("desc") || name.toLowerCase().contains("email")){
                query.like(!ObjectUtils.isEmpty(value), columnName,value);
            }else{
                query.eq(!ObjectUtils.isEmpty(value), columnName,value);
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /***
     * 解析字段名字
     * @param field
     * @param columnName
     * @return
     */
    @Nullable
    public static String getColumnName(Field field, String columnName) {
        TableField tableField = field.getAnnotation(TableField.class);

        //如果是逻辑删除字段，或者数据库不存在的字段，则不进行查询
        if(field.getAnnotation(TableLogic.class)!=null || (tableField!=null && !tableField.exist())){
            return null;
        }
        //从主键或者非主键获取字段名字
        TableId tableId = field.getAnnotation(TableId.class);
        if(tableField!=null && !ObjectUtils.isEmpty(tableField.value())){
            columnName = tableField.value();
        }else if(tableId!=null && !ObjectUtils.isEmpty(tableId.value())){
            columnName = tableId.value();
        }
        columnName = StringUtils.camelToUnderline(columnName);
        return columnName;
    }

}
